#include "ocv.grpc.pb.h"
#include <grpcpp/grpcpp.h>
#include <opencv2/opencv.hpp>
#include <opencv2/imgcodecs.hpp>
#include <iostream>
#include "config_loader.h"

using grpc::Channel;
using grpc::ClientContext;
using grpc::Status;
using ocv::OcvService;
using ocv::VoidRequest;
using ocv::JpegFrameResponse;

class OcvClient {
 public:
  OcvClient(std::shared_ptr<Channel> channel)
      : stub_(OcvService::NewStub(channel)) {}

  bool GetFrame() {
    ClientContext context;
    VoidRequest request;
    JpegFrameResponse response;

    Status status = stub_->GetFrame(&context, request, &response);

    if (status.ok()) {
      std::vector<uchar> data(response.data().begin(), response.data().end());
      auto frame = cv::imdecode(data, cv::IMREAD_COLOR);
      std::cout << "Received image: " << frame.rows << "x" << frame.cols << std::endl;
      cv::imwrite("frame.jpg", frame);
      return true;
    } else {
      std::cerr << "RPC failed: " << status.error_message() << std::endl;
      return false;
    }
  }

 private:
  std::unique_ptr<OcvService::Stub> stub_;
};

int main(int argc, char** argv) {
    ConfigMap config = ConfigLoader().GetConfig("config.ini");
    std::shared_ptr<Channel> channel(
        grpc::CreateChannel(config.at(SERVER_IP) + ":" +
        config.at(PORT), grpc::InsecureChannelCredentials()));
    OcvClient client(channel);
    if (!client.GetFrame()) {
        return 1;
    }
    return 0;
}